Management API
TideCloak provides a Management API (Keycloak-compatible Admin REST) to manage realms, clients, users, roles, and more. It's ideal for automating provisioning, CI/CD, migrations, and back-office tasks.
1. Prerequisites
- A running TideCloak server (dev, self-hosted, or managed).
- An admin user or a confidential client with service account credentials.
- Network access to the admin endpoints over HTTPS.
Base URLs
- Modern Keycloak/TideCloak (Quarkus):
https://<host>/realms/<realm>/protocol/openid-connect/token
Admin REST base:https://<host>/admin/realms/<realm>/...
- Legacy path (older distros include
/auth
):https://<host>/auth/realms/<realm>/protocol/openid-connect/token
Admin REST base:https://<host>/auth/admin/realms/<realm>/...
Use whichever matches your deployment. Your earlier console URLs should hint which style you're on.
2. Try the API via Swagger
You can experiment with the API using the hosted Swagger UI: https://apidocs.tidecloak.com.
Prereqs
- A realm (e.g.,
swagger-realm
) - A client (e.g.,
swagger-ui
) - A user with a linked Tide account
Steps
- Set Base URL to your TideCloak host.
- Enter the client_id (your client, not
admin-cli
unless that's what you use). - Click Authorize and sign in with your Tide-linked account, or paste a Bearer token.
3. Authentication (Recommended)
A. Recommended: Client Credentials (Service Account)
Create a confidential client with Service accounts enabled and grant it only the required realm-management roles (least privilege!):
- Typical roles:
view-users
,manage-users
,view-clients
,manage-clients
,view-realm
,manage-realm
(pick only what you need).
Token (Bash)
export HOST="https://<host>"
export REALM="master" # or the admin realm you use for tokens
export CLIENT_ID="admin-bot"
export CLIENT_SECRET="<client-secret>"
curl -sS -X POST "$HOST/realms/$REALM/protocol/openid-connect/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=client_credentials" -d "client_id=$CLIENT_ID" -d "client_secret=$CLIENT_SECRET"
4. Common Admin Tasks (cURL)
Replace
TOKEN
with your access token, andADMREALM
with the realm you are administrating (often a non-master
realm).
List users
curl -sS "$HOST/admin/realms/ADMREALM/users?search=bob&first=0&max=20" -H "Authorization: Bearer $TOKEN"
Create a user
curl -sS -X POST "$HOST/admin/realms/ADMREALM/users" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"username": "bob",
"email": "bob@example.com",
"enabled": true
}' -i
# On success returns 201 and a Location header with the new user ID.
Assign a realm role to a user
# 1) Get the role representation
ROLE="admin"
ROLE_JSON=$(curl -sS "$HOST/admin/realms/ADMREALM/roles/$ROLE" -H "Authorization: Bearer $TOKEN")
# 2) Map it to the user
curl -sS -X POST "$HOST/admin/realms/ADMREALM/users/$USER_ID/role-mappings/realm" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d "[$ROLE_JSON]"
Create a client and fetch its secret
# Create client
curl -sS -X POST "$HOST/admin/realms/ADMREALM/clients" -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{
"clientId": "myclient",
"publicClient": false,
"serviceAccountsEnabled": true,
"redirectUris": ["https://app.example.com/*"]
}' -i
# Find client ID by clientId
CID=$(curl -sS "$HOST/admin/realms/ADMREALM/clients?clientId=myclient" -H "Authorization: Bearer $TOKEN" | jq -r '.[0].id')
# Get client secret
curl -sS "$HOST/admin/realms/ADMREALM/clients/$CID/client-secret" -H "Authorization: Bearer $TOKEN"
5. C# HttpClient Examples
Get token (Client Credentials)
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
var host = "https://<host>";
var realm = "master";
var clientId = "admin-bot";
var clientSecret = "<client-secret>";
using var http = new HttpClient();
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("grant_type","client_credentials"),
new KeyValuePair<string,string>("client_id",clientId),
new KeyValuePair<string,string>("client_secret",clientSecret),
});
var tokenRes = await http.PostAsync($"{host}/realms/{realm}/protocol/openid-connect/token", content);
var tokenJson = await tokenRes.Content.ReadAsStringAsync();
// parse access_token and use below
List users
http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var res = await http.GetAsync($"{host}/admin/realms/ADMREALM/users?first=0&max=20");
var body = await res.Content.ReadAsStringAsync();
6. Error Handling Cheat-sheet
- 401 Unauthorized: Missing/expired token.
- 403 Forbidden: Token lacks required
realm-management
permissions. - 404 Not Found: Wrong ID/realm or insufficient privileges hide resources.
- 409 Conflict: Duplicate name/constraint violation (e.g., username exists).
- 400 Bad Request: Invalid payload or parameters.
Log the response body; admin endpoints usually return a useful message.
7. Security & Best Practices
- Prefer Client Credentials with a minimal-scope service account over password grant.
- Assign only needed
realm-management
roles (least privilege). - Use HTTPS, rotate secrets, and store them in a secure secret manager.
- Do not expose admin tokens client-side.
- For production changes requiring governance, document how they're approved in your process (e.g., IGA/Change Requests).
If your realm uses IGA / Change Requests, add a dedicated section explaining how to create, review, and commit change requests via API (endpoints, required roles, and example payloads).
8. Troubleshooting
- Token URL mismatch: If you see 404s on
/realms/.../protocol/openid-connect/token
, try the legacy/auth/realms/...
path (and vice-versa). - CORS: Admin REST is normally for server-to-server; use it from backend services to avoid CORS.
- Swagger auth: If "Authorize" fails, verify client type, redirect URIs, and whether the client is public vs confidential.